package com.ug_project.dict.engine.indextable

import org.junit.Test

import org.junit.Assert.*
import java.nio.channels.FileChannel
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardOpenOption

class PointerBlockTest {

    val file = Paths.get("temp.wdt")

    fun provideIndexTable(action: (table: IndexTable) -> Unit) {
        if (Files.exists(file)) Files.delete(file)
        Files.createFile(file)

        val channel = FileChannel.open(file, StandardOpenOption.WRITE, StandardOpenOption.READ)
        val table = IndexTable(channel)
        action(table)
        channel.close()
        Files.deleteIfExists(file)
    }

    @Test
    fun addNewDataBlock() {
        provideIndexTable {table ->
            val pointerBlockId = table.allocateBlock()
            val pointerBlock = PointerBlock(table, pointerBlockId)

            assertEquals(0, pointerBlock.allPointers.size)

            for (i in 0..9){
                val dataBlock = DataBlock(table, table.allocateBlock()).apply {
                    previousBlockId = i + 65 + 0
                    dataIndex = i + 65 + 1
                    nextBlockId = i + 65 + 2
                    previousWordUnicode = i + 65 + 3
                    nextWordUnicode = i + 65 + 4
                }
                dataBlock.writeToChannel()
                pointerBlock.addNewDataBlock(dataBlock)
            }
            pointerBlock.writeToChannel()

            for (i in 0..9){
                val dataBlock = DataBlock(table, pointerBlock.allPointers[i])
                assertEquals(i + 65 + 0, dataBlock.previousBlockId)
                assertEquals(i + 65 + 1, dataBlock.dataIndex)
                assertEquals(i + 65 + 2, dataBlock.nextBlockId)
                assertEquals(i + 65 + 3, dataBlock.previousWordUnicode)
                assertEquals(i + 65 + 4, dataBlock.nextWordUnicode)
            }
        }
    }

    @Test
    fun removeDataBlock() {
        provideIndexTable { table ->
            val pointerBlock = PointerBlock(table, table.allocateBlock())
            var dataBlock = DataBlock(table, table.allocateBlock()).apply {
                previousBlockId = 10
                dataIndex = 20
                nextBlockId = 30
                previousWordUnicode = 40
                nextWordUnicode = 50

                writeToChannel()
            }
            pointerBlock.addNewDataBlock(dataBlock)
            pointerBlock.writeToChannel()

            dataBlock = DataBlock(table, pointerBlock.allPointers[0])
            dataBlock.apply {
                assertEquals(10, previousBlockId)
                assertEquals(20, dataIndex)
                assertEquals(30, nextBlockId)
                assertEquals(40, previousWordUnicode)
                assertEquals(50, nextWordUnicode)
            }

            assertEquals(1, pointerBlock.allPointers.size)

            pointerBlock.removeDataBlock(dataBlock)
            assertEquals(0, pointerBlock.allPointers.size)
        }
    }
}
